#pragma once

#include "indexed_polyline.h"

namespace outline {

template <typename T>
template <typename I>
indexed_polyline<T>::indexed_polyline(I first, I last) :
	tree_(indexed_polyline<T>(* this))
{
	nodes_.assign(first, last);
	size_ = nodes_.size();
	closed_ = false;
	begin_ = &nodes_[0];

	tree_.reserve(size_);
	for (size_type i = 0; i < size_; ++i)
		tree_.push_back(i);
	tree_.rebalance();
}

template <typename T>
template <typename I>
indexed_polyline<T>::indexed_polyline(I first, I last, size_type ndup) :
	tree_(* this)
{
	I prelast = last;
	std::advance(prelast, -(int)ndup);
	nodes_.assign(prelast, last);
	nodes_.insert(nodes_.end(), first, last);
	size_ = nodes_.size() - ndup;
	I aftfirst = first;
	std::advance(aftfirst, ndup);
	nodes_.insert(nodes_.end(), first, aftfirst);
	closed_ = true;
	begin_ = &nodes_[ndup];

	tree_.reserve(size_);
	for (size_type i = 0; i < size_; ++i)
		tree_.push_back(i);
	tree_.rebalance();
}

template <typename T>
inline typename indexed_polyline<T>::size_type indexed_polyline<T>::size() const
	{ return size_; }

template <typename T>
inline bool indexed_polyline<T>::is_closed() const
	{ return closed_; }

template <typename T>
inline typename indexed_polyline<T>::point_type const & indexed_polyline<T>::operator [] (int n) const
	{ return begin_[n]; }

template <typename T>
inline typename indexed_polyline<T>::size_type indexed_polyline<T>::nearest_node_index_to(point_type const & p) const 
	{ return *tree_.nearest(p, xtd::range_finder(), std::numeric_limits<xtd::range_finder::result_type>::max()); }

template <typename T>
inline typename indexed_polyline<T>::point_type const & indexed_polyline<T>::nearest_node_to(point_type const & p) const 
	{ return (*this)[nearest_node_index_to(p)]; }

} //namespace outline
